home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
networke
/
civ-0.000
/
civ-0
/
civ-0.3
/
src
/
player.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1996-03-04
|
29KB
|
1,070 lines
#include <stdio.h>
#include <stdlib.h>
#ifndef MS_WIN
#include <unistd.h>
#else
int sleep(int n)
{
return 0;
}
#endif
#include "defs.h"
#include "world.h"
#include "player.h"
#include "trans.h"
#include "move.h"
#include "units.h"
#include "graph.h"
#include "keyboard.h"
#include "MsgQ.h"
#include "city.h"
#include "display.h"
#include "misc.h"
#include "rules.h"
#include "savefile.h"
void NetFail(char *str)
{
printf("Network failure %s\n", str);
exit(1);
}
static void FixX(int &x)
{
x = (x-HorizSpace)/SquareWidth;
if (x < 0) x = 0;
if (x >= SquaresWide) x = SquaresWide-1;
}
static void FixY(int &y)
{
y = (y-VertSpace)/SquareHeight;
if (y < 0) y = 0;
if (y >= SquaresHigh) y = SquaresHigh-1;
}
static void ShowPoint(int x, int y)
{
int wx, wy;
if (x >= HorizSpace || y < VertSpace || y >= VertSpace+64) {
FixX(x);
FixY(y);
display->TranslateWorld(x, y, wx, wy);
}
else {
y -= VertSpace;
wx = (x*world->MaxX())/HorizSpace;
wy = (y*world->MaxY())/64;
}
display->Center(wx, wy);
}
// colors for players
static char *color_tbl[] = {
"#e8e8e8e8e8e8", "#0c0ce0e0e8e8",
"#ad00ff002f00", "#e8e8e8e8e8e8",
"NavyBlue", "#e8e8e8e8e8e8",
"DarkGray", "#e8e8e0e0e8e8" };
Player::Player(char *Name, int Id)
{
name = Name;
sprintf(color1Str, "x c %s", color_tbl[Id*2]);
sprintf(color2Str, "x c %s", color_tbl[Id*2+1]);
id = Id;
cityPic = 0;
doneMoving = 0;
govt = DESPOT;
tax = 50;
luxuries = 0;
money = 0;
initiatedSave = 0;
templeEffect = 1;
cathedralEffect = 4;
seamoveBonus = 0;
tradeBonus = 0;
if (!savedGame)
InitialScience(id, discovered, canDiscover, canBuild, canGovern);
researching = NULL;
scienceAcc = 0;
needScience = 10;
state = NORMAL;
}
Player::~Player()
{
delete name;
}
int Player::HasWonder(char *name)
{
for (Lister<charp> l = wonders; l; l.Next())
if (strcmp(l.Elem(), name) == 0) return 1;
return 0;
}
void Player::DeleteWonder(char *name)
{
for (Lister<charp> l = wonders; l; l.Next())
if (strcmp(l.Elem(), name) == 0) {
l.Delete();
return;
}
}
long Player::CompilePic(char **pic)
{
char *ptr1 = pic[1], *ptr2 = pic[2];
color1Str[0] = ptr1[0];
color2Str[0] = ptr2[0];
pic[1] = color1Str;
pic[2] = color2Str;
long handle = screen->CompilePixmap(pic);
pic[1] = ptr1;
pic[2] = ptr2;
return handle;
}
// create the first settler for the player
void Player::Setup()
{
// find a nice random place on the map which has at least a
// 5x5 block of land around it
Debug('i', "Trying to setup\n");
int x, y;
while (1) {
while (1) {
x = random() % world->MaxX();
y = random() % world->MaxY();
int goodspot = 1;
for (int x1 = -2; x1 <= 2; ++x1) for (int y1 = -2; y1 <= 2; ++y1)
if (world->Terrain((x+x1+world->MaxX())%world->MaxX(),
(y+y1+world->MaxY())%world->MaxY()) == WATER)
{ goodspot = 0; break; }
if (goodspot) break;
}
if (!world->NextToOpponent(id,x,y)) break;
}
// Unit constructor automatically adds it to the world and to the
// list of units for the player
Debug('i', "found spot %d %d\n", x, y);
Unit *settler = NewUnit(SETTLER, id, trans->New(), 0, 0, x, y);
moveQ = new MsgQ;
*moveQ << PieceMove(settler->id, PIECE_CREATE, x, y, SETTLER,
0, 0);
}
// send all the moves across
void Player::SendMoves(MsgQ *q)
{
*q << "moves";
Debug('p', "sending moves\n");
*q << *moveQ;
delete moveQ;
moveQ = NULL;
}
// show the moves made
void Player::ShowMoves(MsgQ *q, MsgQ *outQ)
{
City *city;
Unit *unit;
char *name;
int fortStat;
while (q->Count() > 0) {
Msg m;
*q >> m;
PieceMove *move = (PieceMove*)m.buf;
move->HostOrder();
switch (move->oper) {
case PIECE_CREATE:
unit = NewUnit(move->type, id, move->id, move->veteran,
move->city, move->x, move->y);
Debug('u', "Created new unit type %d, id %ld, at %d %d\n", move->type,
unit->id, move->x, move->y);
break;
case PIECE_MOVE:
// moving into a city automatically captures it
// if a city is captured and it is the city for the player whose
// civ this is, MoveUnit will tell the city to send its info across
// it must tell the server to send the message to the owner of the
// piece only
MoveUnit(trans->TransUnit(move->id), move->x, move->y, 0.0, outQ);
sleep(1);
break;
case PIECE_DIE:
delete trans->TransUnit(move->id);
break;
case CITY_CREATE:
*q >> name;
city = new City(name, move->id, move->x, move->y, id);
break;
case CITY_DIE:
delete trans->TransCity(move->id);
break;
case CITY_SIZE:
city = trans->TransCity(move->id);
city->size = move->x;
city->DrawIfVisible();
break;
case CITY_WALL:
city = trans->TransCity(move->id);
if (move->x) {
if (!city->HasBuilding("City Walls"))
city->buildings.Insert("City Walls");
} else {
for (Lister<charp> l = city->buildings; l; l.Next())
if (strcmp(l.Elem(),"City Walls")==0) {
l.Delete();
continue;
}
}
city->DrawIfVisible();
break;
case CITY_WORK_MAP:
city = trans->TransCity(move->id);
city->TransWorkMap(q);
break;
case UNIT_UPDATE:
unit = trans->TransUnit(move->id);
fortStat = unit->Fortified();
if (move->x)
unit->Fortify();
else
unit->UnFortify();
if (move->y) unit->MakeVeteran();
if (fortStat != unit->Fortified())
unit->DrawIfVisible();
break;
case DISCOVERY: // some player has discovered something
{
*q >> name;
Player *p = players[move->id];
Discover(move->id, name, p->discovered, p->canDiscover,
p->canBuild, p->canGovern);
delete name;
break;
}
case WONDER: // someone else has built a wonder
{
*q >> name;
Player *p = players[move->id];
BuildObject *obj = buildObjects.Find(StrKey(name));
obj->built = 1;
p->wonders.Insert(obj->name);
AddMessage(players[playerId]->messages, "%s builds %s\n",
p->name, obj->name);
delete name;
}
case TERRAIN_CHANGE:
world->Set(move->x, move->y, move->type);
if (world->Visible(move->x, move->y) &&
display->Visible(move->x, move->y)) {
int sx, sy;
display->TranslateScreen(move->x, move->y, sx, sy);
world->Draw(move->x, move->y, 1, 1, sx, sy);
}
break;
}
delete move;
}
}
void Player::InitMoveTurn()
{
Debug('p', "initmoveturn for %d\n", id);
if (initiatedSave) {
MsgQ *q = new MsgQ;
*q << "save_game";
SendQ(q);
CreateSaveFile();
acks_left = numPlayers-1;
accepts_left = 0;
screen->DisplayMessage("Waiting for save", 0);
}
else {
MsgQ *q = new MsgQ;
*q << "myturn";
*q << id;
SendQ(q);
moveQ = new MsgQ;
acks_left = numPlayers-1;
accepts_left = 0;
screen->DisplayMessage("Your Turn", 0);
doneMoving = 0;
}
}
void Player::MoveTurnMesg(MsgQ *q)
{
char *mesg;
*q >> mesg;
if (initiatedSave && playerId == 0 && strcmp(mesg, "done_save") == 0) {
if (--acks_left <= 0)
exit(0);
}
if (strcmp(mesg, "yourturn_ack") == 0) {
if (--acks_left <= 0) {
// startup moveturn
if (researching == NULL) {
state = IN_SELECT;
selecting = SCIENCE;
screen->CreateChoiceFrame("Choose Research", canDiscover);
}
UpdateCities();
display->ShowPlayerInfo();
currUnit = NULL;
Lister<ulong> unitl = units;
while (unitl) {
Unit *ptr = trans->TransUnit(unitl.Elem());
ptr->numMoves = ptr->Moves(players[playerId]->seamoveBonus);
ptr->CompleteOrder();
if (currUnit == NULL && ptr->numMoves > 0) currUnit = ptr;
unitl.Next();
}
if (currUnit == NULL)
screen->DisplayMessage("End of Turn, press Enter", 0);
else if (state != IN_SELECT) {
display->ShowPiece(currUnit->x, currUnit->y, currUnit->id);
display->EnableCursor(currUnit->x, currUnit->y, currUnit->id);
}
}
}
else if (strcmp(mesg, "got_moves") == 0) {
// if we took over any cities of this guy there will be more messages
if (q->Count() > 0)
GetCapturedCity(q, this);
if (--acks_left <= 0) {
currTurn = (currTurn+1) % numPlayers;
doneMoving = 0;
InitCityTurn();
}
}
else if (strcmp(mesg, "city_info") == 0) {
// get captured city info here
}
delete mesg;
delete q;
return;
}
void Player::SelectEvent(int event, int x, int y, char *data)
{
if (state != IN_SELECT) return;
if (event != SELECT) return;
if (selecting == SCIENCE) { // selecting science
Debug('p', "Selected science %s\n", data);
Science *ptr = sciences.Find(StrKey(data));
researching = ptr->name;
needScience = DiscoverCost(id,ptr);
display->ShowPlayerInfo();
state = NORMAL;
}
// MarkM added government type:
else if (selecting == GOVERNMENT_TYPE) {
if (strcmp(data,"Despotism") == 0) govt = DESPOT;
else if (strcmp(data,"Monarchy") == 0) govt = MONARCH;
else if (strcmp(data,"The Republic") == 0) govt = REPUBLIC;
else if (strcmp(data,"Democracy") == 0) govt = DEMOCRACY;
state = NORMAL;
}
else if (selecting == TAX_RATE) {
sscanf(data, "Tax %d\n", &tax);
for (Lister<ulong> l = citys; l; l.Next())
trans->TransCity(l.Elem())->ComputeEcon();
display->ShowPlayerInfo();
state = NORMAL;
}
// MarkM added luxuries rate:
else if (selecting == LUXURY_RATE) {
sscanf(data, "Luxuries %d\n", &luxuries);
for (Lister<ulong> l = citys; l; l.Next())
trans->TransCity(l.Elem())->ComputeEcon();
display->ShowPlayerInfo();
state = NORMAL;
}
// MarkM added revolution choice:
else if (selecting == REVOLUTION) {
if (strncmp(data,"Yes",3) == 0) govt = ANARCHY;
state = NORMAL;
}
// MarkM added buying current build-project:
else if (selecting == BUILD_BUY) {
if (strncmp(data,"Yes",3) == 0) {
City *city = display->CurrCity();
int cost = (int) ((city->needProd - city->accProd) * 2.5);
if (money >= cost) {
money -= cost;
city->accProd = city->needProd;
city->ShowWorkInProg();
}
}
state = NORMAL;
} else if (selecting == CITY_BUILDING) {
// have to isolate the object
char *endp = strchr(data, '/');
if (endp)
*endp = '\0';
endp = strrchr(data, ' ');
*endp = '\0';
Debug('p', "Selected building %s\n", data);
City *city = display->CurrCity();
BuildObject *obj = buildObjects.Find(StrKey(data));
if (obj != NULL) Debug('p', "Found obj %s\n", obj->name);
city->WorkOn(obj->name);
state = NORMAL;
city->ShowWorkInProg();
}
return;
}
void Player::MoveTurnKey(int event, int x, int y, char *data)
{
int showPiece = 1;
display->DisableCursor();
if (state == IN_SELECT) {
SelectEvent(event, x, y, data);
}
else if (event == MOUSE_RIGHT) { // right button, center the square
ShowPoint(x, y);
showPiece = 0; // if invisible don't show
}
else if (event == MOUSE_LEFT && !doneMoving) {
// check for fortified or sleeping pieces and wake them up
FixX(x); FixY(y);
int wx, wy;
Unit *found = NULL;
display->TranslateWorld(x, y, wx, wy);
for (Lister<ulong> l = world->Units(wx, wy); l; l.Next()) {
Unit *ptr = trans->TransUnit(l.Elem());
if (ptr->currOrder == 's') {
ptr->currOrder = ' ';
ptr->numMoves = ptr->Moves(players[playerId]->seamoveBonus);
found = ptr;
}
else if (ptr->currOrder == 'f') {
ptr->currOrder = ' ';
ptr->UnFortify();
ptr->numMoves = ptr->Moves(players[playerId]->seamoveBonus);
found = ptr;
// tell other players
*moveQ << PieceMove(ptr->id, UNIT_UPDATE, 0,
ptr->Veteran() != 0 ? 1 : 0);
}
}
if ((currUnit == NULL || currUnit->numMoves <= 0) && found != NULL)
currUnit = found;
}
else if (event == KEYBOARD && !doneMoving) {
int key = x;
Lister<ulong> unitl = units;
if (currUnit != NULL) {
if (MovementKey(key)) {
int tmpy = currUnit->y+MoveYDir(key);
int newx = (currUnit->x+MoveXDir(key)+world->MaxX()) % world->MaxX();
int newy = (tmpy+world->MaxY()) % world->MaxY();
#ifdef NEWWORLD
if (newy == tmpy) {
#endif
int terrain = world->Terrain(newx, newy);
if (currUnit->CanMoveOn(terrain, newx, newy)
&& !world->OpponentPresent(playerId,newx,newy)) {
// only diplomat and caravan can move in opponent zone of control
if ((currUnit->type==DIPLOMAT) || (currUnit->type==CARAVAN)
|| !(world->NextToOpponent(playerId,currUnit->x,currUnit->y)
&& world->NextToOpponent(playerId,newx,newy)) )
{
double cost = currUnit->MoveCost(terrain, currUnit->numMoves,
currUnit->x, currUnit->y,
newx, newy);
if (cost < 0)
currUnit->numMoves = 0;
else {
if (!MoveUnit(currUnit, newx, newy, cost, NULL))
currUnit = NULL;
sleep(1);
}
}
#ifdef NEWWORLD
}
#endif
}
else {
// see if the unit can attack an enemy unit
Lister<ulong> unitsl = world->Units(newx, newy);
int canAttack = 0;
while (unitsl && !canAttack) {
Unit *ptr = trans->TransUnit(unitsl.Elem());
if (ptr->ownerId != playerId && currUnit->CanAttack(ptr->Type()))
canAttack = 1;
unitsl.Next();
}
if (canAttack) {
if (!MoveUnit(currUnit, newx, newy, 1.0, NULL))
currUnit = NULL;
sleep(1);
}
}
if (currUnit != NULL && currUnit->numMoves <= 0)
key = 'n';
}
if (key == 'n' && currUnit != NULL) { // select next unit
Lister<ulong> unitl = units;
while (unitl && unitl.Elem() != currUnit->id) unitl.Next();
if (unitl) unitl.Next();
currUnit = NULL;
while (unitl &&
(currUnit = trans->TransUnit(unitl.Elem()))->numMoves <= 0)
unitl.Next();
}
if (currUnit != NULL && !currUnit->Order(key)) {
Debug('p', "Killing unit %d\n", currUnit->id);
delete currUnit;
currUnit = NULL;
}
}
if (currUnit == NULL || currUnit->numMoves <= 0) {
unitl = units;
while (unitl &&
(currUnit = trans->TransUnit(unitl.Elem()))->numMoves <= 0)
unitl.Next();
}
if (currUnit == NULL || currUnit->numMoves <= 0) {
// move turn is done
currUnit = NULL;
screen->DisplayMessage("Waiting for Acknowledgement", 0);
MsgQ *q = new MsgQ;
*q << "turn_done";
*q << id;
SendMoves(q);
SendQ(q);
acks_left = numPlayers-1;
accepts_left = 0;
doneMoving = 1;
}
}
if (!doneMoving && state != IN_SELECT && currUnit != NULL && currUnit->numMoves > 0) {
if (showPiece)
display->ShowPiece(currUnit->x, currUnit->y, currUnit->id);
if (display->Visible(currUnit->x, currUnit->y))
display->EnableCursor(currUnit->x, currUnit->y, currUnit->id);
}
}
City *Player::FindCityWithMsg()
{
for (Lister<ulong> l = citys; l; l.Next()) {
City *city = trans->TransCity(l.Elem());
if (city->messages) return city;
}
return NULL;
}
void Player::InitCityTurn()
{
Debug('p', "InitCityTurn for %d\n", id);
screen->DisplayMessage(players[currTurn]->name, 0);
City *city;
if ((city = FindCityWithMsg()) != NULL) {
display->ShowCityInfo(city);
screen->MessageBox(city->messages.RemoveHead());
}
else if (messages)
screen->MessageBox(messages.RemoveHead());
}
// MarkM added government-type choice:
void Player::ChooseGovernment()
{
state = IN_SELECT;
selecting = GOVERNMENT_TYPE;
screen->CreateChoiceFrame("Choose Government", canGovern);
}
// called when a key is pressed in the city turn
void Player::CityTurnKey(int event, int x, int y, char *data)
{
if (state == IN_SELECT) {
SelectEvent(event, x, y, data);
return;
}
if (event == MESG_READ) {
if (messages)
screen->MessageBox(messages.RemoveHead());
else {
City *city = display->CurrCity();
if (city->messages)
screen->MessageBox(city->messages.RemoveHead());
}
return;
}
if (event == MOUSE_LEFT && display->InMap()) {
FixX(x); FixY(y);
int wx, wy;
display->TranslateWorld(x, y, wx, wy);
if (world->WhichCity(wx, wy) != 0) {
City *city = trans->TransCity(world->WhichCity(wx, wy));
if (city->ownerId != id) return;
display->ShowCityInfo(city);
}
return;
}
if (event == MOUSE_LEFT && display->InCity()) {
x = (x-120)/SquareWidth;
y = (y-24)/SquareHeight;
if (x < 0 || x > 4 || y < 0 || y > 4) return;
x -= 2;
y -= 2;
Debug('c', "Clicked on square %d %d\n", x, y);
if (x == 0 && y == 0) return;
City *city = display->CurrCity();
int wx = (city->x+x+world->MaxX())%world->MaxX();
int wy = (city->y+y+world->MaxY())%world->MaxY();
if (world->RealVisible(wx, wy) == 0) return;
if (world->Working(wx, wy) == city->id) { // take off
world->Working(wx, wy) = 0;
city->ComputeEcon();
city->DrawCityMap();
city->ShowPeople();
city->ShowEcon();
}
else if (world->Working(wx, wy) == 0) {
city->ComputeEcon();
if (city->elvi <= 0) return;
world->Working(wx, wy) = city->id;
city->ComputeEcon();
city->DrawCityMap();
city->ShowPeople();
city->ShowEcon();
}
return;
}
if (event == MOUSE_RIGHT && display->InMap()) {
ShowPoint(x, y);
return;
}
if (event != KEYBOARD) return;
int ch = x;
if (ch == 'a' && players[currTurn]->doneMoving) {
// accepted his moves, show them, if he captured our city
// we will send the info for it across too
display->ShowMap();
Debug('p', "showing players moves\n");
players[currTurn]->doneMoving = 0;
MsgQ *q = new MsgQ;
*q << "got_moves";
players[currTurn]->ShowMoves(players[currTurn]->unDispQ, q);
SendQ(q);
// next player's turn
currTurn = (currTurn+1) % numPlayers;
Debug('p', "currTurn %d, my id %d\n", currTurn, id);
if (currTurn == id) {
InitMoveTurn();
} else {
screen->DisplayMessage(players[currTurn]->name, 0);
}
}
else if (ch == 'c' && display->InCity()) { // change working on
City *city = display->CurrCity();
List<charp> build = city->CanBuild();
state = IN_SELECT;
selecting = CITY_BUILDING;
screen->CreateChoiceFrame("Select ...", build);
build.Delete();
}
else if (ch == 'b' && display->InCity()) { // buy what we're working on
City *city = display->CurrCity();
int cost = (int) ((city->needProd - city->accProd)*2.5);
if (cost > 0 && cost < money) {
List<charp> buyl;
char *str = new char[30];
sprintf(str,"Buy %s ?", city->building);
char *str1 = new char[50];
sprintf(str1,"Yes, buy %s for %d coin",city->building,cost);
buyl.Insert(str1);
char *str2 = new char[50];
sprintf(str2,"No, do not buy %s",city->building);
buyl.Insert(str2);
state = IN_SELECT;
selecting = BUILD_BUY;
screen->CreateChoiceFrame(str, buyl);
buyl.Delete();
}
}
else if (ch == 't' && display->InMap()) {
List<charp> taxl;
// MarkM made max tax rate limited by luxuries rate (and vice-versa):
for (int i = 10-luxuries/10; i >= 0; --i) {
char *str = new char[20];
sprintf(str, "Tax %d%%", i*10);
taxl.Insert(str);
}
state = IN_SELECT;
selecting = TAX_RATE;
screen->CreateChoiceFrame("Set Tax Rate ...", taxl);
while (taxl) delete taxl.RemoveHead();
}
// MarkM added luxuries rate:
else if (ch == 'l' && display->InMap()) {
List<charp> luxl;
for (int i = 10-tax/10; i >= 0; --i) {
char *str = new char[20];
sprintf(str, "Luxuries %d%%", i*10);
luxl.Insert(str);
}
state = IN_SELECT;
selecting = LUXURY_RATE;
screen->CreateChoiceFrame("Set Luxuries Rate ...", luxl);
while (luxl) delete luxl.RemoveHead();
}
else if (ch == 'r') {
world->DrawMainMap();
screen->Refresh();
}
// MarkM added revolution (changing govt type to ANARCHY):
else if (ch == 'g' && display->InMap() && govt != ANARCHY) {
if (HasWonder("Pyramids")) ChooseGovernment();
else {
List<charp> revl;
char *str1 = new char[30];
sprintf(str1,"No revolution thank you.");
revl.Insert(str1);
char *str2 = new char[30];
sprintf(str2,"Yes, time for a revolution!");
revl.Insert(str2);
state = IN_SELECT;
selecting = REVOLUTION;
screen->CreateChoiceFrame("Revoltion?", revl);
while (revl) delete revl.RemoveHead();
}
}
else if (MovementKey(ch) && display->InMap()) {
int xinc = MoveXDir(ch), yinc = MoveYDir(ch);
if (yinc < 0) display->ScrollUp();
if (yinc > 0) display->ScrollDown();
if (xinc < 0) display->ScrollLeft();
if (xinc > 0) display->ScrollRight();
screen->Refresh();
}
else if (ch == 'm' && display->InCity()) {
City *city;
if ((city = FindCityWithMsg()) != NULL) {
display->ShowCityInfo(city);
screen->MessageBox(city->messages.RemoveHead());
}
else
display->ShowMap();
}
else if (ch == 'S') {
if (playerId == 0)
initiatedSave = 1;
else if (initiatedSave) {
CreateSaveFile();
exit(0);
}
}
}
// message in city turn
void Player::CityTurnMesg(MsgQ *q)
{
char *mesg;
*q >> mesg;
if (strcmp(mesg, "myturn") == 0) { // acknowledge a moveturn
int player;
*q >> player;
if (player != currTurn) {
Debug('n',"Myturn from %d; currTurn is %d!\n",player, currTurn);
NetFail("CityTurn");
}
MsgQ *q1 = new MsgQ;
*q1 << "yourturn_ack";
SendQ(q1);
delete q;
}
else if (strcmp(mesg, "turn_done") == 0) {
int player;
*q >> player;
if (player != currTurn) {
Debug('n',"Turndone from %d; currTurn is %d!\n",player, currTurn);
NetFail("CityTurn");
}
char *str;
*q >> str;
delete str;
players[currTurn]->unDispQ = q;
Debug('p', "got turn done from %d\n", currTurn);
if ((numPlayers > 2) && ((currTurn+1) % numPlayers) == id) {
accepts_left = numPlayers-2;
screen->DisplayMessage("Waiting for turn...", 0);
}
else {
players[currTurn]->doneMoving = 1;
screen->DisplayMessage("Done: press Accept", 0);
}
}
else if (accepts_left > 0 && strcmp(mesg,"got_moves") ==0) {
if (--accepts_left <= 0) {
players[currTurn]->doneMoving = 1;
screen->DisplayMessage("Done: press Accept", 0);
}
}
else if (playerId != 0 && strcmp(mesg, "save_game") == 0) {
screen->DisplayMessage("Got Save Request", 0);
initiatedSave = 1;
}
else
delete q;
delete mesg;
}
// update cities
// send the list of places where they are working to everyone too
void Player::UpdateCities()
{
Lister<ulong> cityl = citys;
while (cityl) {
City *city = trans->TransCity(cityl.Elem());
if (city->ownerId != id || !city->Update()) { // lost this city
while (city->units) {
Unit *unit = trans->TransUnit(city->units.RemoveHead());
*moveQ << PieceMove(unit->id, PIECE_DIE, 0, 0);
delete unit;
}
if (city->ownerId == id) { // city died
*moveQ << PieceMove(city->id, CITY_DIE, 0, 0);
cityl.Delete(); // MUST do this first
delete city;
}
else
cityl.Delete();
}
else {
*moveQ << PieceMove(city->id, CITY_WORK_MAP, 0, 0);
int len;
char *cmap = city->MakeWorkMap(len);
*moveQ << Msg(cmap, len);
cityl.Next();
}
}
if (scienceAcc >= needScience && researching != NULL) {
scienceAcc -= needScience;
if (scienceAcc > needScience) scienceAcc = needScience;
Discover(id, researching, discovered, canDiscover, canBuild, canGovern);
*moveQ << PieceMove(id, DISCOVERY, 0, 0);
*moveQ << researching;
researching = NULL;
}
// MarkM added 40% chance if ANARCHY of getting to select govt type:
if (govt == ANARCHY && random() %9 <= 3) ChooseGovernment();
}
void Player::WonderEffect(City *city)
{
for (Lister<charp> l = wonders; l; l.Next()) {
BuildObject *obj = buildObjects.Find(StrKey(l.Elem()));
if (WonderObsolete(obj, id)) {
switch (obj->type) {
case COLOSSUS:
tradeBonus = 0;
break;
case MICHELANGELO:
cathedralEffect = 4;
break;
case ORACLE:
templeEffect = 2;
break;
case LIGHTHOUSE:
if (!HasWonder("Magellan's Expedition")) seamoveBonus = 0;
break;
case MAGELLAN:
if (!HasWonder("Light House")) seamoveBonus = 0;
break;
}
continue;
}
switch (obj->type) {
case COPERNICUS:
if (city->HasBuilding(obj->name))
city->science *= 2;
break;
case CUREFORCANCER:
++city->happy;
break;
case HANGINGGARDENS:
++city->happy;
break;
case HOOVERDAM:
if (city->HasBuilding("Factory"))
city->prod = int(city->prod*1.5);
break;
case ISAACNEWTON:
if (city->HasBuilding("University"))
city->science = int(city->science*1.5);
break;
case JSBACH:
city->goondas -= 2;
if (city->goondas < 0) city->goondas = 0;
break;
case MICHELANGELO:
cathedralEffect = 6;
case ORACLE:
templeEffect = 4;
break;
case SHAKESPEARE:
if (city->HasBuilding(obj->name))
city->goondas = 0;
break;
case LIGHTHOUSE:
case MAGELLAN:
seamoveBonus = 1;
}
}
}
static char *LookupScience(char *str)
{
Debug('p', "Looking up science %s\n", str);
Science *sc = sciences.Find(StrKey(str));
delete str;
if (sc == NULL)
return NULL;
return sc->name;
}
void Player::Save()
{
Debug('s', "Saving player %d\n", id);
WriteUShort(govt);
WriteUShort(tax);
// MarkM added luxuries rate:
WriteUShort(luxuries);
WriteUShort(money);
WriteUShort(scienceAcc);
WriteUShort(needScience);
WriteString(researching == NULL ? "X" : researching);
WriteUChar(templeEffect);
WriteUChar(cathedralEffect);
WriteUChar(seamoveBonus);
WriteUChar(tradeBonus);
WriteUShort(discovered.Count());
Lister<charp> l;
for (l = discovered; l; l.Next())
WriteString(l.Elem());
WriteUShort(canDiscover.Count());
for (l = canDiscover; l; l.Next())
WriteString(l.Elem());
WriteUShort(canBuild.Count());
for (l = canBuild; l; l.Next())
WriteString(l.Elem());
// MarkM added canGovern list of available government types:
WriteUShort(canGovern.Count());
for (l = canGovern; l; l.Next())
WriteString(l.Elem());
WriteUShort(wonders.Count());
for (l = wonders; l; l.Next())
WriteString(l.Elem());
WriteUShort(citys.Count());
Lister<ulong> l1;
for (l1 = citys; l1; l1.Next())
trans->TransCity(l1.Elem())->Save();
WriteUShort(units.Count());
for (l1 = units; l1; l1.Next())
trans->TransUnit(l1.Elem())->Save();
}
void Player::Restore()
{
Debug('s', "Restoring player %d\n", id);
govt = ReadUShort();
tax = ReadUShort();
// MarkM added luxuries rate:
luxuries = ReadUShort();
money = ReadUShort();
scienceAcc = ReadUShort();
needScience = ReadUShort();
researching = LookupScience(ReadString());
Debug('s', "Restored upto researching %s\n", researching);
templeEffect = ReadUChar();
cathedralEffect = ReadUChar();
seamoveBonus = ReadUChar();
tradeBonus = ReadUChar();
int n = ReadUShort();
Debug('s', "Restoring %d discovered\n", n);
for (; n > 0; --n) {
char *name = LookupScience(ReadString());
discovered.Insert(name);
Science *sc = sciences.Find(StrKey(name));
sc->discovered |= 1 << id;
if (sc->wonderObsolete != NULL)
buildObjects.Find(StrKey(sc->wonderObsolete))->isObsolete = 1;
}
n = ReadUShort();
Debug('s', "Restoring %d can discover\n", n);
for (; n > 0; --n)
canDiscover.Insert(LookupScience(ReadString()));
n = ReadUShort();
Debug('s', "Restoring %d can build\n", n);
for (; n > 0; --n) {
char *str = ReadString();
BuildObject *obj = buildObjects.Find(StrKey(str));
delete str;
canBuild.Insert(obj->name);
}
n = ReadUShort();
Debug('s', "Restoring %d can govern\n", n);
for (; n > 0; --n)
canGovern.Insert(LookupScience(ReadString()));
n = ReadUShort();
Debug('s', "Restoring %d wonders\n", n);
for (; n > 0; --n) {
char *str = ReadString();
BuildObject *obj = buildObjects.Find(StrKey(str));
delete str;
wonders.Insert(obj->name);
obj->built = 1;
}
n = ReadUShort();
Debug('s', "Restoring %d cities\n", n);
for (; n > 0; --n)
City *city = new City; // default constructor reads from save file
n = ReadUShort();
Debug('s', "Restoring %d units\n", n);
for (; n > 0; --n)
Unit *unit = new Unit; // default constructor reads from save file
// compute economies
if (playerId == id)
for (Lister<ulong> l = citys; l; l.Next())
trans->TransCity(l.Elem())->ComputeEcon();
}